/*
 * Copyright 2020 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.sample.hello1;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.incubator.codec.quic.InsecureQuicTokenHandler;
import io.netty.incubator.codec.quic.QuicChannel;
import io.netty.incubator.codec.quic.QuicServerCodecBuilder;
import io.netty.incubator.codec.quic.QuicSslContext;
import io.netty.incubator.codec.quic.QuicSslContextBuilder;
import io.netty.incubator.codec.quic.QuicStreamChannel;
import io.netty.util.CharsetUtil;

public final class QuicServerExample {

	private QuicServerExample() {
	}

	public static void main(String[] args) throws Exception {
		SelfSignedCertificate selfSignedCertificate = new SelfSignedCertificate();
		QuicSslContext context = QuicSslContextBuilder
				.forServer(selfSignedCertificate.privateKey(), null, selfSignedCertificate.certificate())
				.applicationProtocols("swakx/1.1").build();
		NioEventLoopGroup group = new NioEventLoopGroup(1);
		ChannelHandler codec = new QuicServerCodecBuilder().sslContext(context)
				.maxIdleTimeout(5000, TimeUnit.MILLISECONDS).initialMaxData(10000000)
				.initialMaxStreamDataBidirectionalLocal(1000000).initialMaxStreamDataBidirectionalRemote(1000000)
				.initialMaxStreamsBidirectional(100).initialMaxStreamsUnidirectional(100)
				.tokenHandler(InsecureQuicTokenHandler.INSTANCE)

				// 设置处理器 -- 这里可以不处理，当然也可以主动的创建流处理
				// 感觉这块也是没有必要的
				.handler(new ChannelInboundHandlerAdapter() {
					@SuppressWarnings("unused")
					@Override
					public void channelActive(ChannelHandlerContext ctx) {
						QuicChannel channel = (QuicChannel) ctx.channel();
						System.out.println("客户端连接");
					}

					public void channelInactive(ChannelHandlerContext ctx) {
						System.out.println("客户端断开连接");
					}

					@Override
					public boolean isSharable() {
						return true;
					}
				})

				// 设置流处理器
				.streamHandler(new ChannelInitializer<QuicStreamChannel>() {
					@Override
					protected void initChannel(QuicStreamChannel ch) {
						ch.pipeline().addLast(new EchoChannelHandler()) // 测试事件
								.addLast(new LineBasedFrameDecoder(1024))// 测试事件
								.addLast(new ChannelInboundHandlerAdapter() {// 测试事件
									@Override
									public void channelRead(ChannelHandlerContext ctx, Object msg) {
										ByteBuf byteBuf = (ByteBuf) msg;
										try {
											if (byteBuf.toString(CharsetUtil.US_ASCII).trim().equals("GET /")) {
												ByteBuf buffer = ctx.alloc().directBuffer();
												buffer.writeCharSequence("Hello World!\r\n", CharsetUtil.US_ASCII);
												ctx.writeAndFlush(buffer);
											}
										} finally {
											byteBuf.release();
										}
									}
								});
					}
				}).build();
		try {
			Bootstrap bs = new Bootstrap();
			Channel channel = bs.group(group).channel(NioDatagramChannel.class).handler(codec)
					.bind(new InetSocketAddress(9999)).sync().channel();
			channel.closeFuture().sync();
		} finally {
			group.shutdownGracefully();
		}
	}
}
